{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Code your own neuron and neural net\n",
    "The parts of code that look like\n",
    "```python\n",
    "pass  # ⬅️✏️\n",
    "```\n",
    "need to be filled in before moving to the next cell.\n",
    "\n",
    "Check out the slides and / or corresponding video lecture for more instructions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "lines_to_next_cell": 1
   },
   "outputs": [],
   "source": [
    "# Define two vectors (lists): input my_x, weights my_w\n",
    "my_x = [0, 1, 1]\n",
    "my_w = [-10, 10, 5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Multiply two lists element wise\n",
    "def mul(a, b):\n",
    "    \"\"\"\n",
    "    return a list c, same length as a, element c[i] = a[i] * b[i]\n",
    "    \"len(list)\" and \"[0] * n\" may be useful\n",
    "    \"\"\"\n",
    "    pass  # ⬅️✏️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Test mul() function\n",
    "mul(my_x, my_w)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "lines_to_next_cell": 1
   },
   "outputs": [],
   "source": [
    "# Define a scalar: bias b\n",
    "my_b = -5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Neuron linear (internal) potential\n",
    "def linear_neuron(x, weights, bias):\n",
    "    \"\"\"\n",
    "    return a scalar value representing a scalar neuron\n",
    "    \"sum(list)\" computes the sum of the elements in a list\n",
    "    \"\"\"\n",
    "    pass  # ⬅️✏️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Test linear_neuron() function\n",
    "linear_neuron(my_x, my_w, my_b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "lines_to_next_cell": 1
   },
   "outputs": [],
   "source": [
    "# Import exp() function (safe on lists)\n",
    "from numpy import exp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Logistic sigmoid\n",
    "def sigmoid(z):\n",
    "    \"\"\"\n",
    "    return the logistic sigmoid (use exp())\n",
    "    \"\"\"\n",
    "    pass  # ⬅️✏️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Try out σ() for different z values\n",
    "for z in (-5, 0, 5): print(sigmoid(z))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import some plotting stuff to graph sigmoid()\n",
    "from numpy import linspace\n",
    "from matplotlib.pyplot import plot, axhline, axvline, grid, style\n",
    "style.use('dark_background')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Get a pair of axis and grid lines centred in (0, 0)\n",
    "axhline(c='.2'); axvline(color='.2')\n",
    "grid(c='.1', ls='--')\n",
    "\n",
    "# Plot across a span of numbers\n",
    "z = linspace(-7.5, 7.5)\n",
    "plot(z, sigmoid(z));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Full neuron function\n",
    "def neuron(x, weights, bias):\n",
    "    \"\"\"\n",
    "    Return a classical neuron output (reuse code above)\n",
    "    \"\"\"\n",
    "    pass  # ⬅️✏️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Test neuron() function\n",
    "neuron(my_x, my_w, my_b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "lines_to_next_cell": 1
   },
   "outputs": [],
   "source": [
    "# Package OR neuron weights and bias\n",
    "def or_neuron(x):\n",
    "    \"\"\"\n",
    "    Return x1 OR x2 (x1 + x2)\n",
    "    \"\"\"\n",
    "    pass  # ⬅️✏️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Defina a collection of inputs to test OR and AND\n",
    "my_x_collection = [\n",
    "    [0, 0],\n",
    "    [0, 1],\n",
    "    [1, 0],\n",
    "    [1, 1],\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "lines_to_next_cell": 1
   },
   "outputs": [],
   "source": [
    "print('Checking OR neuron output')\n",
    "for my_x in my_x_collection:\n",
    "    print(my_x, f'{or_neuron(my_x):.3f}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "lines_to_next_cell": 1
   },
   "outputs": [],
   "source": [
    "# Package AND neuron weights and bias\n",
    "def and_neuron(x):\n",
    "    \"\"\"\n",
    "    Return x1 AND x2 (x1 * x2)\n",
    "    \"\"\"\n",
    "    pass  # ⬅️✏️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "lines_to_next_cell": 1
   },
   "outputs": [],
   "source": [
    "print('Checking AND neuron output')\n",
    "for my_x in my_x_collection:\n",
    "    print(my_x, f'{and_neuron(my_x):.3f}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "lines_to_next_cell": 1
   },
   "outputs": [],
   "source": [
    "# Package NOT neuron weight and bias\n",
    "def not_neuron(x):\n",
    "    \"\"\"\n",
    "    Return NOT x1 (x1_)\n",
    "    \"\"\"\n",
    "    pass  # ⬅️✏️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "lines_to_next_cell": 1
   },
   "outputs": [],
   "source": [
    "print('Checking NOT neuron output')\n",
    "for my_x in [[0], [1]]:\n",
    "    print(my_x, f'{not_neuron(my_x):.3f}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![X-OR](res/x-or_circuit.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Combine OR, AND, and NOT into a XOR neuron\n",
    "def xor_neuron(x):\n",
    "    \"\"\"\n",
    "    Return x1_ * x2 + x1 * x2_\n",
    "    \"\"\"\n",
    "    pass  # ⬅️✏️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('Checking XOR neuron output')\n",
    "for my_x in my_x_collection:\n",
    "    print(my_x, f'{xor_neuron(my_x):.3f}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![Half-adder](res/half-adder_circuit.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Combine a XOR and an AND into a half-adder\n",
    "# ⬅️✏️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![Adder](res/adder_circuit.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Combine two half-adders and an OR into a (full) adder\n",
    "# ⬅️✏️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "encoding": "# -*- coding: utf-8 -*-"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
